package com.smsc.headend.task.engine.handler.impl.deviceconfig;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.json.JSONUtil;
import com.google.common.collect.Lists;
import com.smsc.headend.common.enums.ChannelTypeEnum;
import com.smsc.headend.common.utils.ProtoBufferUtil;
import com.smsc.headend.module.asset.entity.Meter;
import com.smsc.headend.module.data.dto.TaskPacketDTO;
import com.smsc.headend.module.data.enums.OperationGroup;
import com.smsc.headend.module.data.enums.OperationName;
import com.smsc.headend.module.protocol.DeviceData;
import com.smsc.headend.module.protocol.cosem.bo.CosemData;
import com.smsc.headend.module.task.consts.TaskKafkaTopic;
import com.smsc.headend.module.task.dto.AtomicTask;
import com.smsc.headend.module.task.dto.SubTaskGroup;
import com.smsc.headend.module.task.dto.Task;
import com.smsc.headend.module.task.dto.TaskResult;
import com.smsc.headend.module.task.enums.TaskType;
import com.smsc.headend.module.task.proto.TaskProto;
import com.smsc.headend.task.engine.dao.TaskDAO;
import com.smsc.headend.task.engine.exception.UDISTaskHandlerException;
import com.smsc.headend.task.engine.handler.TaskHandler;
import com.smsc.headend.task.engine.service.asset.AssetService;
import com.smsc.headend.task.engine.service.task.TaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Description
 * @Author W26102
 * @Date 2021/8/2 16:16
 * @Sine 1.0
 **/
@Slf4j
public class KeyTransferActionHandler implements TaskHandler {
    public static final String EXTERNAL_MESSAGE_ID = "externalMessageId";
    @Autowired
    TaskDAO taskDAO;
    @Autowired
    TaskService taskService;
    @Autowired
    KafkaTemplate kafkaTemplate;
    @Autowired
    AssetService assetService;

    @Override
    public int handle(Task task, AtomicTask atomicTask, DeviceData deviceData, String actionResult) throws UDISTaskHandlerException {
        log.info("task no:{},atomicTaskNO,{},cosemData:{}, action result {}", task.getTaskNo(), atomicTask.getAtomicTaskNo(), deviceData, actionResult);

        Object data = null;
        sendMessageToAdapter(task, atomicTask, data, null);

        //if pcl meter ,need update dcu info,generate update task
        sendWhiteListMessage(task);

        return 1;
    }

    private void sendWhiteListMessage(Task task) {
        if (Objects.nonNull(task.getMeterId())) {
            Meter meter = assetService.getMeterById(task.getMeterId());
            if (ChannelTypeEnum.PLC.name().equals(meter.getChannelType())) {
                String messageId = task.getMessageId();
                String taskNo = UUID.randomUUID().toString();
                Integer keyTransferWhitelistResetRtySpan = Convert.toInt(assetService.getSystemProperty("KEY_TRANSFER_WHITELIST_RESET_RTY_SPAN"));
                log.info("comId:{} ,meterId :{}  is plc type ,send message trigger white list task,messageId:{},taskNo:{}, retryTime:{}, interval={}",
                        task.getComId(), meter.getMeterId(), messageId, taskNo, 3, keyTransferWhitelistResetRtySpan);
                Task whiteListTask = new Task();
                whiteListTask.setIsODR(false);
                whiteListTask.setMessageId(messageId);
                whiteListTask.setTaskNo(taskNo);
                whiteListTask.setRetryTimes(3);
                whiteListTask.setRetryIntervalSeconds(keyTransferWhitelistResetRtySpan == null ? 3600 : keyTransferWhitelistResetRtySpan);
                whiteListTask.setTaskType(TaskType.WhiteListSet.toString());
                Map<String, Object> param = new HashMap<>();
                whiteListTask.setComId(task.getComId());
                whiteListTask.setPriority(Task.Priority.NORMAL.getPriorityCode());

                List<SubTaskGroup> subTaskGroups = new ArrayList<>();
                SubTaskGroup subTaskGroup = new SubTaskGroup();
                subTaskGroup.setGroupId(OperationGroup.DCUSetMeterList.getId().longValue());
                AtomicTask atomicWhiteTask = new AtomicTask();
                atomicWhiteTask.setAtomicTaskNo(UUID.randomUUID().toString());
                atomicWhiteTask.setTaskNo(whiteListTask.getTaskNo());
                atomicWhiteTask.setOperationId(OperationName.SetData.getId().longValue());
                atomicWhiteTask.setGroupId(OperationGroup.DCUSetMeterList.getId().longValue());
                atomicWhiteTask.setSeq(0);
                subTaskGroup.setSubTasks(Lists.newArrayList(atomicWhiteTask));

                param.put("meterIds", new ArrayList<Long>() {{
                    add(meter.getMeterId());
                }});
                subTaskGroups.add(subTaskGroup);
                whiteListTask.setParamJson(JSONUtil.toJsonStr(param));
                whiteListTask.setSubTaskGroups(subTaskGroups);
                taskService.sendTaskToGenerator(whiteListTask);
            }
        }
    }

    private void sendMessageToAdapter(Task task, AtomicTask atomicTask, Object data, String message) {
        TaskResult taskResult = new TaskResult();
        taskResult.setTaskNo(task.getTaskNo());
        taskResult.setResultData(data);
//        Map<String, Object> dataItemMap = JSONUtil.toBean(atomicTask.getAtomicTaskParam(), Map.class);
//        taskMap.putAll(dataItemMap);
        Map<String, Object> taskMap = JSONUtil.toBean(task.getParamJson(), Map.class);
        taskResult.setMessageId(task.getMessageId());

        List<TaskPacketDTO> taskPacketDTOList = taskService.getTaskPacket(task.getTaskNo());
        if (CollectionUtil.isNotEmpty(taskPacketDTOList)) {
            log.info("key transfer  packet result are: {}", JSONUtil.toJsonStr(taskPacketDTOList));
            taskMap.put("packets", taskPacketDTOList);
        } else {
            log.error("key transfer data item reply without packets! taskNo: {}", task.getTaskNo());
        }
        taskResult.setParamJson(JSONUtil.toJsonStr(taskMap));
        if (!StringUtils.isEmpty(message)) {
            taskResult.setExceptionCause(message);
        }
        kafkaTemplate.send(TaskKafkaTopic.TASK_COMPLETE_RESULT_FROM_UTE_TO_ADAPTER, JSONUtil.toJsonStr(taskResult).getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public int handleFailure(Task task, AtomicTask atomicTask, String message) {
        log.info("error {},task no:{},atomic no:{} ", message, task.getTaskNo(), atomicTask.getAtomicTaskNo());
        sendMessageToAdapter(task, atomicTask, null, message);
        return -1;
    }
}
